// Package random 随机生成器
package random

import (
	randc "crypto/rand"
	"github.com/golang/freetype/truetype"
	"image"
	"image/color"
	"math"
	"math/big"
	"math/rand"
	"time"
)

const (
	// MaximumCapacity 随机数最大容量
	MaximumCapacity = math.MaxInt>>1 + 1
	// Numeral 数字
	Numeral = "0123456789"
	// Lowercase 小写字母
	Lowercase = "abcdefghijklmnopqrstuvwxyz"
	// Uppercase 大写字母
	Uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	// Alpha 字母
	Alpha = Lowercase + Uppercase
	// Special 特殊字符
	Special = "!@#$%^&*()_+-=[]{};':\",./<>?"
	// All 所有字符
	All = Numeral + Alpha + Special
)

// rand
var rn = rand.NewSource(time.Now().UnixNano())
var rnd = rand.New(rn)

// RandBool 随机生成bool
// true: 1/2
func RandBool() bool {
	return rand.Intn(2) == 1
}

// RandBoolSlice 随机生成bool数组
// length: 长度
// true: 1/2
func RandBoolSlice(length int) []bool {
	if length <= 0 {
		return []bool{}
	}
	result := make([]bool, length)
	for i := 0; i < length; i++ {
		result[i] = RandBool()
	}
	return result
}

// RandIntByRange 随机生成指定范围的整数
// min: 最小值, max: 最大值
// min <= x <= max
// 随机生成整数
func RandIntByRange(min, max int) int {
	if min == max {
		return min
	}
	if max <= min {
		min, max = max, min
	}
	if min == 0 && max == math.MaxInt {
		return rand.Int()
	}
	return rand.Intn(max-min) + min
}

// RandIntSliceByRange 随机生成指定长度的数组，元素在指定范围内
// length: 长度, min: 最小值, max: 最大值
// min <= x <= max
// 随机生成数组，元素在指定范围内
func RandIntSliceByRange(length, min, max int) []int {
	if length <= 0 || min > max {
		return []int{}
	}
	result := make([]int, length)
	for i := range result {
		result[i] = RandIntByRange(min, max)
	}
	return result
}

// RandIntUniqueSliceByRange 随机生成指定长度的数组，元素在指定范围内且不重复
// length: 长度, min: 最小值, max: 最大值
// min <= x <= max
// 随机生成数组，元素在指定范围内且不重复
func RandIntUniqueSliceByRange(length, min, max int) []int {
	if length <= 0 || min > max {
		return []int{}
	}
	result := make([]int, length)
	used := make(map[int]struct{}, length)
	for i := 0; i < length; {
		rnTempValue := RandIntByRange(min, max)
		_, ok := used[rnTempValue]
		if ok {
			continue
		}
		used[rnTempValue] = struct{}{}
		result[i] = rnTempValue
		i++
	}
	return result
}

// RandFloat 随机生成小数
// min: 最小值, max: 最大值
// min <= x <= max
// 随机生成小数
func RandFloat(min, max float64, precision int) float64 {
	if min == max {
		return min
	}
	if min >= max {
		min, max = max, min
	}
	tmpF := rand.Float64()*(max-min) + min
	// 浮点数精度
	return tmpF
}

// Rand63N 随机生成指定范围的整数
func Rand63N(ri int64) {
	rnd.Int63n(ri)
}

func Rand31n(ri int32) {
	rnd.Int31n(ri)
}

// GetPerm 随机生成指定长度的数组，元素在指定范围内且不重复
// n: 长度
func GetPerm(n int) []int {
	return rnd.Perm(n)
}

// GetRandInt 随机生成指定范围的整数
// min: 最小值, max: 最大值
// 随机生成整数
func GetRandInt(min, max int) int {
	if min > max {
		return max
	}
	if min < 0 {
		f64min := math.Abs(float64(min))
		i64min := int(f64min)
		result, _ := randc.Int(randc.Reader, big.NewInt(int64(max+i64min)))
		return int(result.Int64()) - i64min
	}

	result, _ := randc.Int(randc.Reader, big.NewInt(int64(max-min+1)))
	return int(result.Int64()) + min
}

// RandFont 随机返回字体
// fonts: 字体
// 随机返回字体
func RandFont(fonts []*truetype.Font) *truetype.Font {
	index := RandIndex(len(fonts))
	if index < 0 {
		return nil
	}
	return fonts[index]
}

// RandIndex 随机生成指定长度的数组，元素在指定范围内且不重复
// length: 长度
// 随机生成数组，元素在指定范围内且不重复
func RandIndex(length int) int {
	if length == 0 {
		return -1
	}
	index := GetRandInt(0, length)
	if index >= length {
		index = length - 1
	}
	return index
}

// RandHexColor 随机返回颜色
// colors: 颜色
// 随机返回颜色
func RandHexColor(colors []string) string {
	index := RandIndex(len(colors))
	if index < 0 {
		return ""
	}
	return colors[index]
}

// RandImage 随机返回图片
// images: 图片
// 随机返回图片
func RandImage(images []image.Image) image.Image {
	index := RandIndex(len(images))
	if index < 0 {
		return nil
	}
	return images[index]
}

// RandString 随机返回字符串
// chars: 字符串
// 随机返回字符串
func RandString(chars []string) string {
	k := rand.Intn(len(chars))
	return chars[k]
}

// RandColor 随机返回颜色
// co: 颜色
// 随机返回颜色
func RandColor(co []color.Color) color.RGBA {
	colorLen := len(co)
	index := GetRandInt(0, colorLen)
	if index >= colorLen {
		index = colorLen - 1
	}
	r, g, b, a := co[index].RGBA()
	return color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: uint8(a)}
}

// RandCutImagePos 随机返回图片裁剪位置
// width: 宽度, height: 高度, img: 图片
// 随机返回图片裁剪位置
func RandCutImagePos(width, height int, img image.Image) image.Point {
	b := img.Bounds()
	iw := b.Max.X
	ih := b.Max.Y
	curX := 0
	curY := 0
	if iw-width > 0 {
		curX = GetRandInt(0, iw-width)
	}
	if ih-height > 0 {
		curY = GetRandInt(0, ih-height)
	}
	return image.Point{X: curX, Y: curY}
}
